<?php

namespace Our\Upload;

/**
 * 上传功能
 */
class Main {

    /**
     * 默认配置
     * 
     * @var Application_Model_Business_Upload_Config 
     */
    protected $_config = null;

    public function __construct(\Our\Upload\Config $config = null) {
        if (!$config) {
            $config = new \Our\Upload\Config();
        }
        $this->_config = $config;
    }

    /**
     * 上传文件
     * @return array [保存的相对目录，保存的绝对目录，保存的文件名]
     * @throws \Exception
     */
    public function upload() {
        $upload = new \Zend\File\Transfer\Transfer();
        $upload->addValidator('Size', false, $this->_config->getSize());
        $upload->addValidator('Extension', false, implode(',', $this->_config->getExt()));
        if (!$upload->isValid()) {
            throw new \Exception('文件大小或格式不符合', 900001);
        }

        $fileInfo   = $upload->getFileInfo();
        $methodName = $this->_config->getSubDirType() . 'CalcSavePath';
        if (!method_exists($this, $methodName)) {
            throw new \Exception('计算文件保存目录的方法不存在', 900002);
        }
        list($dir, $fullDir, $filename) = $this->$methodName($fileInfo);

        $this->makeDir($fullDir);
        $upload->setDestination($fullDir);
        $upload->addFilter('Rename', array('target' => $filename, 'overwrite' => true));

        $upload->receive();

        return array($dir, $fullDir, $filename);
    }

    /**
     * md5方式计算文件保存路径
     * 
     * @param array $fileInfo zend获取的文件信息
     * @return array 保存的文件路径和名称
     */
    protected function md5CalcSavePath($fileInfo) {
        $dir     = $this->_config->getDir();
        $extName = $this->getExtension($fileInfo[$this->_config->getFilename()]['name']);

        if ($this->_config->getSaveFilename()) {
            $finalDir = $dir;
            $fullDir  = $this->getFullPath($dir);

            $filename = $this->_config->getSaveFilename() . '.' . $extName;
        } else {
            $md5      = md5_file($fileInfo[$this->_config->getFilename()]['tmp_name']);
            $subDir   = implode('/', str_split(substr($md5, 0, 28), 4));
            $finalDir = rtrim($dir, '/') . '/' . $subDir;
            $fullDir  = $this->getFullPath($finalDir);

            $filename = substr($md5, 28) . '.' . $extName;
        }

        return array($finalDir, $fullDir, $filename);
    }

    /**
     * 计算文件保存路径
     * 
     * @param array $fileInfo zend获取的文件信息
     * @return array array(保存的相对目录，保存的绝对目录，保存的文件名)
     */
    protected function dateCalcSavePath($fileInfo) {
        $dir     = $this->_config->getDir();
        $extName = $this->getExtension($fileInfo[$this->_config->getFilename()]['name']);

        if ($this->_config->getSaveFilename()) {
            $finalDir = $dir;
            $fullDir  = $this->getFullPath($dir);

            $filename = $this->_config->getSaveFilename() . '.' . $extName;
        } else {
            $subDir   = date('/Y/m/d');
            $finalDir = rtrim($dir, '/') . $subDir;
            $fullDir  = $this->getFullPath($finalDir);

            $filename = date('His') . rand(100000, 999999) . '.' . $extName;
            while (file_exists(rtrim($fullDir, '/') . '/' . $filename)) {
                $filename = date('His') . rand(100000, 999999) . '.' . $extName;
            }
        }

        return array($finalDir, $fullDir, $filename);
    }

    /**
     * 保持上传文件的原文件名不变
     * @param type $fileInfo
     * @return type
     */
    protected function originCalcSavePath($fileInfo) {
        $dir     = $this->_config->getDir();
        $extName = $this->getExtension($fileInfo[$this->_config->getFilename()]['name']);
        if ($this->_config->getSaveFilename()) {
            $finalDir = $dir;
            $fullDir  = $this->getFullPath($dir);

            $filename = $this->_config->getSaveFilename() . '.' . $extName;
        } else {
            $finalDir = $dir;
            $fullDir  = $this->getFullPath($finalDir);
            $filename = $fileInfo[$this->_config->getFilename()]['name'];
        }

        return array($finalDir, $fullDir, $filename);
    }

    /**
     * 根据相对路径获取绝对路径

     * @param string $path
     * @return string
     */
    public function getFullPath($path = null) {
        $root = realpath(APPLICATION_PATH . "/public");
        if (is_string($path) && strlen($path) > 0) {
            $root = $root . ($path[0] == '/' ? $path : "/$path");
            $root = str_replace(array('/', '\\', '//', '\\\\'), DIRECTORY_SEPARATOR, $root);
        }
        return $root;
    }

    /**
     * 获取文件扩展名
     * 
     * @param string $path
     * @return string
     */
    public function getExtension($fileName) {
        if (!$fileName) {
            return '';
        }
        $exts = explode(".", $fileName);
        $n    = count($exts) - 1;
        $ext  = $exts[$n];
        return $ext;
    }

    /**
     * 创建目录
     * 
     * @param string $path
     * @return boolean
     */
    public function makeDir($path) {
        if (DIRECTORY_SEPARATOR == "\\") {//windows os
            $path = iconv('utf-8', 'gbk', $path);
        }
        if (!$path) {
            return false;
        }
        if (file_exists($path)) {
            return true;
        }
        if (mkdir($path, 0777, true)) {
            return true;
        }
        return false;
    }

}
